package com.appdemo.demo;

import java.util.EnumSet;
import java.util.Optional;

/**
 * 枚举常用行为
 * @author panpengwen
 * @date 2020/11/17
 */
public interface EnumCode<T> {

    /**
     * 获取错误编码
     * @return 错误码
     */
    T getCode();

    /**
     * 比较某个枚举值是否和指定的枚举值一致
     * @param code 枚举值
     * @return true: 相等, false: 不相等
     */
    default boolean equalsTo(T code) {
        return this.getCode().equals(code);
    }


    /**
     * 获取枚举编码
     * @param enumCode 枚举
     * @param <T>      值类型
     * @return return {@code null} if enmCode is null, otherwise {@link #getCode()}.
     */
    static <T> Optional<T> decode(EnumCode<T> enumCode) {
        return Optional.ofNullable(enumCode != null ? enumCode.getCode() : null);
    }

    /**
     * 将枚举编码转换成枚举
     * <p>
     * 注意:会通过{@code equals()}方法对{@linkplain EnumCode#getCode()}返回值与value进行比较
     * @param type  枚举类型
     * @param value 枚举值
     * @param <E>
     * @return
     */
    static <E extends Enum<E>> Optional<E> encode(Class<E> type, Object value) {

        if (value == null) {
            return Optional.empty();
        }

        EnumSet<E> enums = EnumSet.allOf(type);
        for (Enum<E> en : enums) {
            if (!(en instanceof EnumCode)) {
                throw new IllegalArgumentException(type + " is not implemented " + EnumCode.class);
            }

            EnumCode<E> code = (EnumCode<E>) en;
            Object codeVal = code.getCode();
            if (codeVal.equals(value)) {
                return Optional.of((E) en);
            }
        }

        return Optional.empty();
    }
}
